package com.rest.client.demo;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collections;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public final class RESTfulProvider {

	public static Object get(String url) throws RuntimeException {
		// Create a new RestTemplate instance
		RestTemplate restTemplate = new RestTemplate();
		// Make the HTTP GET request, marshaling the response from JSON to an
		// array of Events
		Object result = restTemplate.getForObject(url, Object.class);

		return result;
	}

	public static <Tresult extends Serializable> Tresult get(String url,
			Tresult result) throws RuntimeException {
		// Create a new RestTemplate instance
		RestTemplate restTemplate = new RestTemplate();
		// Make the HTTP GET request, marshaling the response from JSON to an
		// array of Events
		result = restTemplate.getForObject(url, getClass(result));

		return result;
	}

	public static Object get(String url, String token) throws RuntimeException {
		// Create a new RestTemplate instance
		RestTemplate restTemplate = new RestTemplate();
		// Set the Accept header
		HttpHeaders requestHeaders = new HttpHeaders();
		requestHeaders.setAccept(Collections.singletonList(new MediaType(
				"application", "json")));
		HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);

		// Make the HTTP GET request, marshaling the response from JSON to an
		// array of Events
		ResponseEntity<Object> responseEntity = restTemplate.exchange(url,
				HttpMethod.GET, requestEntity, Object.class);
		Object result = responseEntity.getBody();

		return result;
	}

	public static <Tresult extends Serializable> Tresult get(String url,
			String token, Tresult result) throws RuntimeException {
		// Create a new RestTemplate instance
		RestTemplate restTemplate = new RestTemplate();
		// Set the Accept header
		HttpHeaders requestHeaders = new HttpHeaders();
		requestHeaders.setAccept(Collections.singletonList(new MediaType(
				"application", "json")));
		HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);

		// Make the HTTP GET request, marshaling the response from JSON to an
		// array of Events
		ResponseEntity<Tresult> responseEntity = restTemplate.exchange(url,
				HttpMethod.GET, requestEntity, getClass(result));
		result = responseEntity.getBody();

		return result;
	}

	public static <Tdata extends Serializable> Object post(String url,
			String token, Tdata data) {
		// Create a new RestTemplate instance
		RestTemplate restTemplate = new RestTemplate();
		// Set the Content-Type header
		HttpHeaders requestHeaders = new HttpHeaders();
		requestHeaders.setContentType(new MediaType("application", "json"));
		HttpEntity<Tdata> requestEntity = new HttpEntity<Tdata>(data,
				requestHeaders);

		// Make the HTTP POST request, marshaling the request to JSON, and the
		// response to a String
		ResponseEntity<Object> responseEntity = restTemplate.exchange(url,
				HttpMethod.POST, requestEntity, Object.class);
		Object result = responseEntity.getBody();

		return result;
	}

	public static <Tdata extends Serializable, Tresult extends Serializable> Tresult post(
			String url, String token, Tdata data, Tresult result) {
		// Create a new RestTemplate instance
		RestTemplate restTemplate = new RestTemplate();
		// Set the Content-Type header
		HttpHeaders requestHeaders = new HttpHeaders();
		requestHeaders.setContentType(new MediaType("application", "json"));
		HttpEntity<Tdata> requestEntity = new HttpEntity<Tdata>(data,
				requestHeaders);

		// Make the HTTP POST request, marshaling the request to JSON, and the
		// response to a String
		ResponseEntity<Tresult> responseEntity = restTemplate.exchange(url,
				HttpMethod.POST, requestEntity, getClass(result));
		result = responseEntity.getBody();

		return result;
	}

	@SuppressWarnings("unchecked")
	private static <T> Class<T> getClass(T obj) {
		return (Class<T>) ((ParameterizedType) obj.getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}
}
